package com.hpf.community.config;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.hpf.community.constants.CommunityConstants;
import com.hpf.community.model.AuthModel;
import com.hpf.community.service.IAuthService;
import com.hpf.community.shiro.CommunityRealm;
import com.hpf.community.shiro.CommunityRealmAuthorizer;
import com.hpf.community.shiro.PasswordHelper;
import com.hpf.community.shiro.RoleFilter;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.xpath.operations.String;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @Description:
 * @Author: hpf
 * @Date: 2020/4/17 17:15
 */
@Configuration
public class ShiroConfig {

    @Autowired
    private IAuthService authService;

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

    //加入注解的使用，不加入这个注解不生效
    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }

    //第四步创建ShiroFilterFactoryBean,创建过滤工厂
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
        shiroFilterFactoryBean.setLoginUrl("/login.html");//设置登录界面
        shiroFilterFactoryBean.setSuccessUrl("/index.html");//设置成功界面
        shiroFilterFactoryBean.setUnauthorizedUrl("/error.html");//设置失败未授权页面
        //设置可以多角色问题
        Map<String, Filter> filtersMap = new LinkedHashMap<>();
        filtersMap.put("roles",new RoleFilter());
        shiroFilterFactoryBean.setFilters(filtersMap);

        shiroFilterFactoryBean.setFilterChainDefinitionMap(setFilterChainDefinitionMap());
        return shiroFilterFactoryBean;
    }

    //第三步，创建DefaultWebSecurityManager，安全管理类
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("communityRealm") CommunityRealm communityRealm){
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        CommunityRealmAuthorizer authorizer = new CommunityRealmAuthorizer();
        defaultWebSecurityManager.setAuthorizer(authorizer);
        defaultWebSecurityManager.setRealm(communityRealm);
        return defaultWebSecurityManager;
    }


    //第二步，创建realm
    @Bean
    public CommunityRealm communityRealm(HashedCredentialsMatcher hashedCredentialsMatcher){
        CommunityRealm communityRealm = new CommunityRealm();
        communityRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        return communityRealm;
    }

    /**
     * 第一步 密码加密
     * @param: []
     * @return: org.apache.shiro.authc.credential.HashedCredentialsMatcher
     * @author: HPF
     * @date: 2020/4/17 19:51
     */
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashAlgorithmName(PasswordHelper.ALGORITHM_NAME); // 散列算法
        hashedCredentialsMatcher.setHashIterations(PasswordHelper.HASH_ITERATIONS); // 散列次数
        return hashedCredentialsMatcher;
    }

    @Bean
    public PasswordHelper passwordHelper() {
        return new PasswordHelper();
    }



    private Map<String, String> setFilterChainDefinitionMap() {
        Map<String, String> filterMap = new LinkedHashMap<>();
        //公开访问的资源
        filterMap.put("/css/**","anon");
        filterMap.put("/img/**","anon");
        filterMap.put("/js/**","anon");
        filterMap.put("/lib/**","anon");
        filterMap.put("/emailLogin.html","anon");
        filterMap.put("/login", "anon");
        filterMap.put("/emailRandom", "anon");
        filterMap.put("/emailCheck", "anon");
        filterMap.put("/activityList", "anon");
        filterMap.put("/home/data", "anon");
        filterMap.put("/logout", "logout");
        filterMap.put("/**", "authc");
        //注册 数据库中所有的权限 及其对应url
        Wrapper<AuthModel> wrapper = new EntityWrapper<>();
        wrapper.eq(AuthModel.STATUS, CommunityConstants.USER_STATUS_ZC);
        List<AuthModel> allPermission = authService.selectList(wrapper);//数据库中查询所有权限
        for (AuthModel p : allPermission) {
            filterMap.put(p.getUrl(), "perms[" + p.getName() + "]"); //拦截器中注册所有的权限
        }
        return filterMap;
    }
}
